﻿using System;
using System.Drawing;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Drawing.Printing;
using ContactPrinter.Extension;
using ContactPrinter.Model.Interfaces;

namespace ContactPrinter.Logic
{
    public class FullContactPrinter : PrintDocument
    {
        private IList<IContact> contactsToPrint;
        private int currentContactIndex;

        private readonly Font fontNormal = new Font("Times New Roman", 12);
        private readonly Font fontCaption = new Font("Times New Roman", 30);
        private readonly Brush color = Brushes.Black;

        private const int offsetXPhoneType = 950;
        private const int offsetXPhoneNumber = 1000;
        private const int offsetXAddress = 300;
        private const int offsetX = 10;

        private const int marginTop = 50;
        private const int marginBottom = 100;
        private readonly int maxY;
        private const int pixelBetweenContacts = 8;
        private const int lineHight = 22;

        public FullContactPrinter()
        {
            DefaultPageSettings.PaperSource.SourceName = "A4";
            DefaultPageSettings.Landscape = true;
            maxY = DefaultPageSettings.PaperSize.Height - DefaultPageSettings.Margins.Bottom -
                   DefaultPageSettings.Margins.Top - marginTop - marginBottom;
        }

        public void PrintContacts(IList<IContact> contacts)
        {
            Contract.Requires<ArgumentNullException>(contacts != null);
            contactsToPrint = contacts;

        }

        protected override void OnBeginPrint(PrintEventArgs e)
        {
            currentContactIndex = 0;
            base.OnBeginPrint(e);
        }

        protected override void OnPrintPage(PrintPageEventArgs e)
        {
            var currentPositionY = marginTop;
            string lastCaption = null;

            while (currentContactIndex < contactsToPrint.Count)
            {
                if (currentPositionY >= maxY)
                {
                    e.HasMorePages = true;
                    break;
                }
                
                var currentContact = contactsToPrint[currentContactIndex];
                if (currentContact == null)
                    break;

                //can the next contact be printed on this page?
                int requiredPixelForContact = GetRequiredPixelForContact(currentContact);
                if (currentPositionY + requiredPixelForContact >= maxY)
                {
                    e.HasMorePages = true;
                    break;
                }

                var currentCaption = currentContact.CategoryCapital;
                if (currentCaption != lastCaption)
                {
                    if (currentPositionY + requiredPixelForContact + fontCaption.Height >= maxY)
                    {
                        e.HasMorePages = true;
                        break;
                    }
                    e.Graphics.DrawString(currentCaption, fontCaption, color, offsetX, currentPositionY);
                    lastCaption = currentCaption;
                    currentPositionY += fontCaption.Height;
                }

                DrawContact(e.Graphics, currentPositionY, currentContact);

                currentPositionY += requiredPixelForContact + pixelBetweenContacts;
                currentContactIndex++;
            } 
        }

        private static int GetRequiredPixelForContact(IContact currentContact)
        {
            return currentContact.GetNumberOfLines() * lineHight;
        }

        private void DrawContact(Graphics graphics, int y, IContact contact)
        {
            //Name
            graphics.DrawString(contact.DisplayedName, fontNormal, color, offsetX, y);

            //Address
            var internalYOffset = y;
            foreach (var postalAddress in contact.PostalAddresses)
            {
                var lineString = postalAddress.FormattedAddress.Replace("\n", " - ");
                graphics.DrawString(lineString, fontNormal, color, offsetXAddress, internalYOffset);
                internalYOffset += lineHight;
            }

            //Phone
            internalYOffset = y;
            foreach (var phoneNumer in contact.Phonenumbers)
            {
                graphics.DrawString(phoneNumer.Type.ToString(), fontNormal, color, offsetXPhoneType, internalYOffset);
                graphics.DrawString(phoneNumer.Number, fontNormal, color, offsetXPhoneNumber, internalYOffset);
                internalYOffset += lineHight;
            }
        }

       
    }
}